package com.qqt.csr.common.utils;

import cn.hutool.core.thread.RejectPolicy;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadPoolUtil {

    public static ThreadPoolExecutor newThreadPoolExecutorCallerRunsRejectPolicy(int corePoolSize,
                                                                                 int maximumPoolSize,
                                                                                 long keepAliveTime,
                                                                                 int queueCapacity,
                                                                                 String threadNamePrefix) {
        return new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(queueCapacity),
                ThreadUtil.createThreadFactory(threadNamePrefix),
                RejectPolicy.CALLER_RUNS.getValue());
    }

    /**
     * 关闭线程池
     *
     * @param threadPool
     */
    public static void shutdownThreadPoolGracefully(ExecutorService threadPool) {
        if (threadPool==null || threadPool.isTerminated()) {
            return;
        }
        try {
            threadPool.shutdown();
        } catch (SecurityException | NullPointerException e) {
            log.error(e.getMessage(), e);
            return;
        }
        try {
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                threadPool.shutdownNow();
                if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                    log.info("线程池任务未正常执行结束");
                }
            }
        } catch (InterruptedException ie) {
            threadPool.shutdownNow();
        }
        if (!threadPool.isTerminated()) {
            try {
                for (int i = 0; i < 1000; i++) {
                    if (threadPool.awaitTermination(10, TimeUnit.MILLISECONDS)) {
                        break;
                    }
                    threadPool.shutdownNow();
                }
            } catch (Throwable e) {
                log.error(e.getMessage(), e);
            }
        }
    }
}
